﻿// (c) Copyright 2013 Mike Riedel.
// This source is subject to the Microsoft Public License (Ms-PL).
// All other rights reserved.

using System;
using FreshMeat.Threading;

namespace FreshMeat.Storage
{
   /// <summary>
   /// Stores data in a file system where each data item is stored in a separate file.
   /// </summary>
   /// <typeparam name="TId">Type of ID that uniquely represents each data item.</typeparam>
   /// <typeparam name="TData">Type of data to be stored.</typeparam>
   public class FileStore<TId, TData> : IStore<TId,TData>
   {
      readonly FileLocator<TId> locator;
      readonly ISerializer<TData> serializer;
      readonly ILock locatorLock;

      /// <summary>
      /// Creates instance using a default <see cref="FileLocator{TId}"/>.
      /// </summary>
      /// <param name="fileSystem">File system to use.</param>
      /// <param name="serializer">Serializer to use.</param>
      public FileStore(IFileSystem fileSystem, ISerializer<TData> serializer)
         : this(new FileLocator<TId>(fileSystem), serializer)
      {
      }

      /// <summary>
      /// Creates instance using specified parameters.
      /// </summary>
      /// <param name="locator">File locator to be used.</param>
      /// <param name="serializer">Serializer to be used.</param>
      public FileStore(FileLocator<TId> locator, ISerializer<TData> serializer)
      {
         if (locator == null)
            throw new ArgumentNullException("locator");
         if (serializer == null)
            throw new ArgumentNullException("serializer");

         this.locator = locator;
         this.serializer = serializer;

         locatorLock = new Lock();
      }

      /// <summary>
      /// Creates a context through which operations are performed against this store.
      /// Operations made through a context are isolated from operations made through other contexts.
      /// Contexts should be used and disposed as quickly as possible.
      /// </summary>
      /// <returns></returns>
      public IStoreContext<TId, TData> CreateContext()
      {
         return new FileStoreContext<TId, TData>(locator, serializer, locatorLock);
      }
   }
}